package com.javafactroy.kunlong.bip.icp.socket.server;

import com.javafactroy.kunlong.bip.icp.common.config.BipConfig;
import com.javafactroy.kunlong.bip.icp.factory.AppMessageFactory;
//import com.javafactroy.kunlong.icp.message.dxp.base.Message;
import com.javafactroy.kunlong.bip.icp.message.base.iface.IMessage;
import com.javafactroy.kunlong.bip.icp.message.dxp.base.DxpMsg;
import com.javafactroy.kunlong.bip.icp.message.dxp.base.DxpMsgResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author leijmdas
 * @date 2021/9/14
 * @ddescription:
 */
@Component
@Slf4j
public class SocketTcpServer {
    @Autowired
    BipConfig bipConfig;

    private static Boolean running = false;
    private static ThreadPoolExecutor threadPool;

    public void reply2Client(Socket socket, IMessage msg) throws Exception {
        OutputStream outputStream = socket.getOutputStream();
        DxpMsgResp DxpMsgResp = (DxpMsgResp) AppMessageFactory.execute(msg);
        //Thread.sleep(2000);
        outputStream.write(DxpMsgResp.encode());
        log.info("reply2Client messageRsp: " + DxpMsgResp);
        outputStream.close();
    }

    public class ServerSocketHandler implements Runnable {
        Socket socket;
        public ServerSocketHandler(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                handlerMessage();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        public void handlerMessage() throws Exception {

            log.info("socket服务端 = " + socket.getClass());
            InputStream inputStream = socket.getInputStream();
            //io读
            byte[] bytes = new byte[4];
            int readLen = inputStream.read(bytes);
            if (readLen != -1) {

                DxpMsg message = new DxpMsg();
                message.decodeLen(bytes);
                ByteBuffer buf = ByteBuffer.allocate(message.getTotalLen());
                buf.put(bytes);
                log.info("server reveive message ilen: {}", message.getTotalLen());

                byte[] body = new byte[message.getTotalLen() - 4];
                readLen = inputStream.read(body);
                if (readLen != -1) {
                    DxpMsg msgBody = new DxpMsg();
                    //msgBody.setIlen(message.getIlen() - 4);
                    buf.put(body);
                    msgBody.decode(buf);

                    log.info("*** server reveive len={}, msgBody: {} ", msgBody.getTotalLen(), msgBody);
                    if (false) {
                        running = false;
                    } else {
                        reply2Client(socket, msgBody);
                    }
                }
            }
            inputStream.close();
        }
    }

    //@Autowired
    //private Environment env;

    public void startUp() throws IOException {
        String ip = bipConfig.getProps().getProperty("server.ip");
        String port = bipConfig.getProps().getProperty("server.port");
        ServerSocket serverSocket = new ServerSocket(Integer.valueOf(port));
        log.info("服务端在端口:{}监听，等待连接...", port);
        running = true;
        threadPool = new ThreadPoolExecutor(10, 15, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        while (running) {
            try {
                Socket socket = serverSocket.accept();
                threadPool.submit(new ServerSocketHandler(socket));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //关闭流
        //serverSocket.close();
    }

    public static void main(String[] args) throws IOException {

        new SocketTcpServer().startUp();

    }
}
